{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "from mpl_toolkits.axes_grid1 import make_axes_locatable\n",
    "\n",
    "import numpy\n",
    "import numpy as np\n",
    "import math\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1",
   "metadata": {},
   "outputs": [],
   "source": [
    "matplotlib.style.use('ggplot')\n",
    "matplotlib.rcParams.update({'font.size': 12})\n",
    "matplotlib.rcParams.update({'xtick.labelsize': 'x-large'})\n",
    "matplotlib.rcParams.update({'xtick.major.size': '0'})\n",
    "matplotlib.rcParams.update({'ytick.labelsize': 'x-large'})\n",
    "matplotlib.rcParams.update({'ytick.major.size': '0'})\n",
    "matplotlib.rcParams.update({\"text.usetex\": True})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2",
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(theta, alpha, omega):\n",
    "    val =  1 / (1 + np.exp( -omega * (np.cos(theta) - np.cos(alpha))))\n",
    "    vmax = 1 / (1 + np.exp( -omega * (1 - np.cos(alpha))))\n",
    "    vmin = 1 / (1 + np.exp( -omega * (-1 - np.cos(alpha))))\n",
    "    return (val - vmin) / (vmax - vmin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3",
   "metadata": {},
   "outputs": [],
   "source": [
    "xx = np.arange(-3.2,3.2,0.01)\n",
    "\n",
    "fig,ax = plt.subplots()\n",
    "\n",
    "oms = [2,5,10,20,50]\n",
    "\n",
    "alpha = np.pi/3\n",
    "for o in oms:\n",
    "    ax.plot(xx, f(xx, alpha, o))\n",
    "\n",
    "plt.legend([f\"$\\omega={o}$\" for o in oms])\n",
    "\n",
    "plt.setp(ax,\n",
    "         xticks = [-np.pi,-2*alpha,-alpha,alpha,2*alpha,np.pi,0],\n",
    "         xticklabels = [\"$-\\pi$\",\"$-2\\pi/3$\",\"$-\\pi/3$\",\"$\\pi/3$\",\"$2\\pi/3$\",\"$\\pi$\",0],\n",
    "         #ylabel = \"$f$\",\n",
    "         title = r\"Modulator $f(\\theta, \\alpha=\\pi/3, \\omega)$\",\n",
    "         xlabel = \"$\\\\theta$\" \n",
    "        )\n",
    "plt.show(fig)\n",
    "fig.savefig('../patchy-modulator.svg', bbox_inches='tight')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4",
   "metadata": {},
   "outputs": [],
   "source": [
    "greymap = matplotlib.colormaps['Greys']\n",
    "norm = matplotlib.colors.Normalize(vmin=0, vmax=1)\n",
    "\n",
    "bluemap = matplotlib.colormaps['Blues']\n",
    "norm2 = matplotlib.colors.Normalize(vmin=0, vmax=1.4)\n",
    "\n",
    "def draw_patchy_particle(ax, xy, director, alpha, omega, rcut):\n",
    "    ax.set_axis_off()\n",
    "    ax.set_aspect('equal')\n",
    "\n",
    "    theta_director = numpy.rad2deg(numpy.arctan2(director[1], director[0]))\n",
    "\n",
    "    extra = 30 # to capture the fade out of the patch\n",
    "    n = 100\n",
    "    dtheta = 2*(alpha+extra) / n\n",
    "    for i in range(n):\n",
    "        init_value = theta_director-alpha-extra\n",
    "        offset = dtheta*i\n",
    "        correction = 0.04\n",
    "        colorscale = greymap(norm(f(np.deg2rad(-alpha-extra + dtheta * i), np.deg2rad(alpha), omega)))[0]\n",
    "        wedge = matplotlib.patches.Wedge(\n",
    "            xy,\n",
    "            rcut,\n",
    "            init_value + offset,\n",
    "            init_value + offset + dtheta + correction, # dtheta is width of wedge, correction gets rid of hairline gaps between them\n",
    "            alpha = 1 - colorscale,\n",
    "            zorder=1,\n",
    "            #color = bluemap(norm2(f(np.deg2rad(-alpha-extra + dtheta * i), np.deg2rad(alpha), omega))),\n",
    "            linewidth=0 # to avoid edges overlapping\n",
    "        )\n",
    "        wedge = ax.add_patch(wedge)\n",
    "\n",
    "    circle = matplotlib.patches.Circle(xy, rcut, zorder=2, ec='k',\n",
    "                                      fill=False,\n",
    "                                      linestyle=(5, (1, 8)))\n",
    "    ax.add_patch(circle)\n",
    "\n",
    "    unit_director = numpy.array(director) / numpy.linalg.norm(director)\n",
    "    arrow = matplotlib.patches.FancyArrow(\n",
    "        xy[0],\n",
    "        xy[1],\n",
    "        unit_director[0],#*rcut,\n",
    "        unit_director[1],#*rcut,\n",
    "        color='k',\n",
    "        zorder=circle.get_zorder() + 1,\n",
    "        width=0.03,\n",
    "        length_includes_head=True,\n",
    "        capstyle='projecting',\n",
    "    )\n",
    "    ax.add_patch(arrow)\n",
    "    # adjust plot limits\n",
    "    new_extent = rcut + max(abs(xy[0]), abs(xy[1]))\n",
    "    old_extent = ax.get_xlim()[1]\n",
    "    extent = max(new_extent, old_extent)\n",
    "    ax.set_xlim(-extent, extent)\n",
    "    ax.set_ylim(-extent, extent)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5",
   "metadata": {},
   "outputs": [],
   "source": [
    "arrowopts = dict(color = 'k', zorder = 3, width = 0.03, length_includes_head=True)\n",
    "\n",
    "fig, ax = matplotlib.pyplot.subplots()\n",
    "\n",
    "p1_x = -1.5\n",
    "p2_x = 1.5\n",
    "alpha = 70\n",
    "omega = 10\n",
    "\n",
    "draw_patchy_particle(ax, (p1_x,0), (1, 0.7), alpha, omega, 1.45)\n",
    "draw_patchy_particle(ax, (p2_x,0), (-1, 0.4), alpha, omega, 1.45)\n",
    "\n",
    "ax.add_patch(matplotlib.patches.FancyArrow(\n",
    "    p1_x,\n",
    "    0,\n",
    "    p2_x-p1_x,\n",
    "    0,\n",
    "    capstyle='projecting',\n",
    "    **arrowopts\n",
    "))\n",
    "\n",
    "theta_director = np.rad2deg(numpy.arctan2(0.7, 1))\n",
    "ax.add_patch(matplotlib.patches.Arc([p1_x,0],1.3,1.3, theta1=0, theta2=theta_director, color='k', linewidth=1.5,))\n",
    "ax.text(-0.7, 0.22, r'$\\theta_i$', size=16, ha='center', va='center')\n",
    "\n",
    "ax.add_patch(matplotlib.patches.Arc([p1_x,0],3,3, theta1=theta_director, theta2 = theta_director + alpha, color='k', linewidth=1.5, capstyle='projecting'))\n",
    "ax.text(p1_x+0.9, -p1_x+0.02, r'$\\alpha$', size=16, ha='center', va='center')\n",
    "\n",
    "theta_director = np.rad2deg(numpy.arctan2(0.4, -1))\n",
    "ax.add_patch(matplotlib.patches.Arc([p2_x,0],1.5,1.5, theta1=theta_director, theta2 = 180, color='k', linewidth=1.5))\n",
    "ax.text(0.43, 0.22, r'$\\theta_j$', size=16, ha='center', va='center')\n",
    "\n",
    "\n",
    "ax.text(0.5, -0.4, r'$\\vec{r}_{ij}$', size=16, color='k')\n",
    "ax.text(1.1*p1_x, -0.3, r'$i$', size=16, ha='center', va='center')\n",
    "ax.text(1.1*p2_x, -0.3, r'$j$', size=16, ha='center', va='center')\n",
    "\n",
    "ax.set_ylim([-2,2])\n",
    "\n",
    "# rot = np.deg2rad(30)\n",
    "# lx = -2.5\n",
    "# ly = -2.5\n",
    "# ll = 1\n",
    "# ax.add_line(matplotlib.lines.Line2D([lx,lx+ll*np.cos(rot)],[ly,ly+ll*np.cos(rot)],color='k',linewidth=0.5))\n",
    "# #ax.text(ll-0.05,-0.1, \"$x$\")\n",
    "# ax.add_line(matplotlib.lines.Line2D([lx,lx+ll*np.cos(rot+np.pi/2)],[ly,ly+ll*np.sin(rot+np.pi/2)],color='k',linewidth=0.5))\n",
    "#ax.text(-0.1,ll-0.05, \"$y$\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig.savefig('../patchy-pair.svg', bbox_inches='tight')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7",
   "metadata": {},
   "outputs": [],
   "source": [
    "arrowopts = dict(color = 'k', zorder = 3, width = 0.03, length_includes_head=True)\n",
    "\n",
    "fig, ax = matplotlib.pyplot.subplots()\n",
    "\n",
    "p1_x = 0\n",
    "p2_x = 1.5\n",
    "alpha = 70\n",
    "omega = 10\n",
    "\n",
    "rcut = 1.2\n",
    "draw_patchy_particle(ax, (p1_x,0), (1, 0.7), alpha, omega, rcut)\n",
    "#draw_patchy_particle(ax, (p2_x,0), (-1, 0.4), alpha, omega, 1.4)\n",
    "\n",
    "# ax.add_patch(matplotlib.patches.FancyArrow(\n",
    "#     p1_x,\n",
    "#     0,\n",
    "#     p2_x-p1_x,\n",
    "#     0,\n",
    "#     capstyle='projecting',\n",
    "#     **arrowopts\n",
    "# ))\n",
    "\n",
    "\n",
    "ll = 1.4\n",
    "ax.add_line(matplotlib.lines.Line2D([0,ll],[0,0],color='k',linewidth=0.5))\n",
    "ax.text(ll-0.05,-0.1, \"$x$\")\n",
    "ax.add_line(matplotlib.lines.Line2D([0,0],[0,ll],color='k',linewidth=0.5))\n",
    "ax.text(-0.1,ll-0.05, \"$y$\")\n",
    "ax.set_xlim([-ll,ll])\n",
    "ax.set_ylim([-ll,ll])\n",
    "\n",
    "\n",
    "theta_director = np.rad2deg(numpy.arctan2(0.7, 1))\n",
    "# ax.add_patch(matplotlib.patches.Arc([p1_x,0],2,2, theta1=0, theta2=theta_director, color='k', linewidth=1.5,))\n",
    "# ax.text(-0.7, 0.22, r'$\\theta_i$', size=16, ha='center', va='center')\n",
    "\n",
    "ax.add_patch(matplotlib.patches.Arc([p1_x,0],2.5,2.5, theta1=theta_director, theta2 = theta_director + alpha, color='k', linewidth=1.5, capstyle='projecting'))\n",
    "ax.text(0.4, 1, r'$\\alpha$', size=16, ha='center', va='center')\n",
    "\n",
    "# theta_director = np.rad2deg(numpy.arctan2(0.4, -1))\n",
    "# ax.add_patch(matplotlib.patches.Arc([p2_x,0],2,2, theta1=theta_director, theta2 = 180, color='k', linewidth=1.5))\n",
    "# ax.text(0.32, 0.22, r'$\\theta_j$', size=16, ha='center', va='center')\n",
    "\n",
    "director = (1,0.7)\n",
    "unit_director = numpy.array(director) / numpy.linalg.norm(director)\n",
    "\n",
    "\n",
    "arrow = matplotlib.patches.FancyArrow(\n",
    "    0,\n",
    "    0,\n",
    "    unit_director[0]*rcut,\n",
    "    unit_director[1]*rcut,\n",
    "    color='k',\n",
    "    width=0.03,\n",
    "    length_includes_head=True,\n",
    "    capstyle='projecting',\n",
    ")\n",
    "# ax.add_patch(arrow)\n",
    "\n",
    "ax.text(0.5, 0.2, r'$\\vec{p}$', size=16, color='k')\n",
    "# ax.text(1.1*p1_x, -0.3, r'$i$', size=16, ha='center', va='center')\n",
    "# ax.text(1.1*p2_x, -0.3, r'$j$', size=16, ha='center', va='center')\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8",
   "metadata": {},
   "outputs": [],
   "source": [
    "fig.savefig('../patchy-def.svg', bbox_inches='tight')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
